home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / sipp / libsipp / viewpoin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-03  |  6.4 KB  |  266 lines

  1. /**
  2.  ** sipp - SImple Polygon Processor
  3.  **
  4.  **  A general 3d graphic package
  5.  **
  6.  **  Copyright Equivalent Software HB  1992
  7.  **
  8.  ** This program is free software; you can redistribute it and/or modify
  9.  ** it under the terms of the GNU General Public License as published by
  10.  ** the Free Software Foundation; either version 1, or any later version.
  11.  ** This program is distributed in the hope that it will be useful,
  12.  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  ** GNU General Public License for more details.
  15.  ** You can receive a copy of the GNU General Public License from the
  16.  ** Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  **/
  18.  
  19. /**
  20.  ** viewpoint.c - Functions that handles the viewpoint definition and
  21.  **               calculation of viewing transformation.
  22.  **/
  23.  
  24. #include <geometric.h>
  25. #include <smalloc.h>
  26. #include <viewpoint.h>
  27. #include <sipp.h>
  28.  
  29.  
  30. Camera         *sipp_current_camera;/* Current camera used as viewpoint */
  31. Camera         *sipp_camera;        /* Pointer to internal camera */
  32. static Camera   intern_camera;      /* Internal camera */
  33.  
  34.  
  35. /*
  36.  * Constants used in viewing transformation.
  37.  */
  38. double        hither;          /* Hither z-clipping plane */
  39. double        yon;             /* Yonder z-clipping plane */
  40.  
  41.  
  42.  
  43. /*
  44.  * Initialize the internal camera.
  45.  */
  46. void
  47. camera_init()
  48. {
  49.     sipp_camera = &intern_camera;
  50.     camera_params(sipp_camera, 0.0, 0.0, 10.0,  0.0, 0.0, 0.0,  
  51.                                0.0, 1.0, 0.0,  0.25);
  52.     camera_use(sipp_camera);
  53. }
  54.  
  55.  
  56. /*
  57.  * Create a virtual camera.
  58.  */
  59. Camera *
  60. camera_create()
  61. {
  62.     Camera *cp;
  63.  
  64.     cp = (Camera *)smalloc(sizeof(Camera));
  65.     camera_params(cp, 0.0, 0.0, 10.0,  0.0, 0.0, 0.0,  0.0, 1.0, 0.0,  0.25);
  66.     return cp;
  67. }
  68.  
  69.  
  70. /*
  71.  * Return memory used by a virtual camera.
  72.  */
  73. void
  74. camera_destruct(cp)
  75.     Camera *cp;
  76. {
  77.     if (cp != sipp_camera) {
  78.         sfree(cp);
  79.         if (cp == sipp_current_camera) {
  80.             camera_use(sipp_camera);
  81.         }
  82.     }
  83. }
  84.  
  85.  
  86. /*
  87.  * Change the position of a virtual camera.
  88.  */
  89. void 
  90. camera_position(cp, x, y, z)
  91.     Camera *cp;
  92.     double  x, y, z;
  93. {
  94.     MakeVector(cp->position, x, y, z);
  95. }
  96.  
  97.     
  98. /*
  99.  * Change the point a virtual camera is "looking" at.
  100.  */
  101. void 
  102. camera_look_at(cp, x, y, z)
  103.     Camera *cp;
  104.     double  x, y, z;
  105. {
  106.     MakeVector(cp->lookat, x, y, z);
  107. }
  108.     
  109.  
  110. /*
  111.  * Set the up vector of a virtual camera.
  112.  */
  113. void 
  114. camera_up(cp, x, y, z)
  115.     Camera *cp;
  116.     double  x, y, z;
  117. {
  118.     MakeVector(cp->up, x, y, z);
  119. }
  120.     
  121.  
  122. /*
  123.  * Set the focal factor of a virtual camera.
  124.  */
  125. void 
  126. camera_focal(cp, focal)
  127.     Camera *cp;
  128.     double  focal;
  129. {
  130.     cp->focal_ratio = focal;
  131. }
  132.  
  133.  
  134. /*
  135.  * Set all parameters in a virtual camera in a single call.
  136.  */
  137. void 
  138. camera_params(cp, x0, y0, z0, x, y, z, ux, uy, uz, ratio)
  139.     Camera *cp;
  140.     double  x0, y0, z0, x, y, z, ux, uy, uz, ratio;
  141. {
  142.     MakeVector(cp->position, x0, y0, z0);
  143.     MakeVector(cp->lookat, x, y, z);
  144.     MakeVector(cp->up, ux, uy, uz);
  145.     cp->focal_ratio = ratio;
  146. }
  147.  
  148.  
  149. /*
  150.  * Set the current viewpoint parameters to be
  151.  * the ones in the virtyal camera pointed to by CP.
  152.  */
  153. void camera_use(cp)
  154.     Camera *cp;
  155. {
  156.     sipp_current_camera = cp;
  157. }
  158.  
  159.  
  160. /*
  161.  * Build a transformation matrix for transformation
  162.  * into view coordinates from a particular camera position.
  163.  */
  164. void
  165. get_view_transf(view_mat, camera, render_mode)
  166.     Transf_mat *view_mat;
  167.     Camera     *camera;
  168.     int         render_mode;
  169. {
  170.     Vector tmp;
  171.     double transl[3];
  172.     double vy, vz;
  173.     int i, j;
  174.     
  175.  
  176.      
  177.     /*
  178.      * We need a translation so the origo
  179.      * of the view coordinate system is placed
  180.      * in the viewpoint.
  181.      */
  182.     transl[0] = -camera->position.x;
  183.     transl[1] = -camera->position.y;
  184.     transl[2] = -camera->position.z;
  185.  
  186.  
  187.     /*
  188.      * Calculate a vector from the viewpoint to the looked at
  189.      * point and use it's length to define heuristic values 
  190.      * for hither and yon.
  191.      */
  192.     VecSub(tmp, camera->lookat, camera->position);
  193.     hither = VecLen(tmp) / ZCLIPF;
  194.     yon    = VecLen(tmp) * ZCLIPF;
  195.  
  196.  
  197.     /*
  198.      * Then we need a rotation that makes the
  199.      * up-vector point up, and alignes the sightline
  200.      * with the z-axis.
  201.      * This code might seem magic but the algebra behind
  202.      * it can be found in Jim Blinn's Corner in IEEE CG&A July 1988
  203.      */
  204.     vecnorm(&tmp);
  205.     vecnorm(&camera->up);
  206.     vz = VecDot(tmp, camera->up);
  207.     if ((vz * vz) > 1.0) {        /* this should not happen, but... */
  208.         vz = 1.0;
  209.     }
  210.     vy = sqrt(1.0 - vz * vz);
  211.     if (vy == 0.0) {          /* oops, the world collapses... */
  212.         vy = 1.0e10;
  213.         vz = 1.0;
  214.     } else {
  215.         vy = 1.0 / vy;
  216.     }
  217.  
  218.     view_mat->mat[0][2] = tmp.x;
  219.     view_mat->mat[1][2] = tmp.y;
  220.     view_mat->mat[2][2] = tmp.z;
  221.  
  222.     VecScalMul(tmp, vz, tmp);
  223.     VecSub(tmp, camera->up, tmp);
  224.     view_mat->mat[0][1] = tmp.x * vy;
  225.     view_mat->mat[1][1] = tmp.y * vy;
  226.     view_mat->mat[2][1] = tmp.z * vy;
  227.  
  228.     view_mat->mat[0][0] = (view_mat->mat[1][1] * view_mat->mat[2][2] 
  229.                            - view_mat->mat[1][2] * view_mat->mat[2][1]);
  230.     view_mat->mat[1][0] = (view_mat->mat[2][1] * view_mat->mat[0][2] 
  231.                            - view_mat->mat[2][2] * view_mat->mat[0][1]);
  232.     view_mat->mat[2][0] = (view_mat->mat[0][1] * view_mat->mat[1][2] 
  233.                            - view_mat->mat[0][2] * view_mat->mat[1][1]);
  234.  
  235.  
  236.     /*
  237.      * Install the translation into the matrix.
  238.      * Note that it is PRE-multiplied into the matrix.
  239.      */
  240.     for (i = 0; i < 3; i++) {
  241.         view_mat->mat[3][i] = 0.0;
  242.         for (j = 0; j < 3; j++) {
  243.             view_mat->mat[3][i] += transl[j] * view_mat->mat[j][i];
  244.         }
  245.     }
  246.  
  247.  
  248.     /*
  249.      * Since the screen coordinates are defined in a left handed
  250.      * coordinate system, we must switch the sign of the first
  251.      * column in the matrix to get appropriate signs of x-values
  252.      * unless LINE rendering is used. In that case we switch the
  253.      * y-axis also to get the origin in the image in the upper left.
  254.      */
  255.     if (render_mode == LINE) {
  256.         view_mat->mat[0][1] = -view_mat->mat[0][1];
  257.         view_mat->mat[1][1] = -view_mat->mat[1][1];
  258.         view_mat->mat[2][1] = -view_mat->mat[2][1];
  259.         view_mat->mat[3][1] = -view_mat->mat[3][1];
  260.     } 
  261.     view_mat->mat[0][0] = -view_mat->mat[0][0];
  262.     view_mat->mat[1][0] = -view_mat->mat[1][0];
  263.     view_mat->mat[2][0] = -view_mat->mat[2][0];
  264.     view_mat->mat[3][0] = -view_mat->mat[3][0];
  265. }
  266.